/* -----------------
* brief
* 1. this is code gen by tools
* 2. mvc code are driver by the model defined with the same filename,
	 for example:
	 there is a Xmodel struct define in xmodel.go file, after the script run (lego model-mvc module_name xmodel)
     it will auto create the code under the module's path
	 m --> xmodel.go
	 v --> view
	 c --> xmodel_ctrl
* 3. you should modify this code if it doesn't satisfy your purpose
*/

package controller

import (
	"encoding/json"
	"errors"
	"github.com/mjiulee/lego"
	"github.com/valyala/fasthttp"
	"saas_sys_base/common"
	appmanagerService "saas_sys_base/modules/appmanager/service"
	configService "saas_sys_base/modules/config/service"
	. "saas_sys_base/modules/tenant/models"
	. "saas_sys_base/modules/tenant/service"
	userService "saas_sys_base/modules/user/service"
)

var _TenantApiCtrl *TenantApiCtrl

type TenantApiCtrl struct {
	tenantService       TenantService
	wxTenantUserService WxTenantUserService
	appManagerService   appmanagerService.AppManagerService
	tenantMemberService TenantMemberService
	appconfigService    configService.AppConfigService
}

func GetInstanceTenantApiCtrl() *TenantApiCtrl {
	return _TenantApiCtrl
}

func init() {
	vc := new(TenantApiCtrl)
	_TenantApiCtrl = vc
	_ctrlList = append(_ctrlList, vc)
}

func (vc *TenantApiCtrl) CtrlInfo() string {
	return "UserApiCtrl"
}

func (vc *TenantApiCtrl) RoutInit() {

	//业务接口
	// 1. 创建租户
	lego.APIPOST("/api/sys/tenant/create_tenant_with_member", vc.CreateTenantWithMember, true)

	//lego.APIPOST("/api/tenant/login", vc.TenantUserLogin, false)  //TODO 此接口要废除，review一下是否要废除
}

/* 获取token
* params:
  ---
*/
type CreateTenantWithMemberResp struct {
	TenantMember TenantMember
	Tenant       Tenant
}

func (vc *TenantApiCtrl) CreateTenantWithMember(ctx *fasthttp.RequestCtx) {
	ctxExt := lego.RequestCtxExtent{ctx}
	response := make(map[string]interface{})
	//data := make(map[string]interface{})
	sessionData := common.GetSessionData(&ctxExt)
	type Resp struct {
		CreateTenantWithMemberResp
	}
	code := 0
	msg := "success"

	for {
		//BODY内json数据的定义
		type Request struct {
			/*Code   string `json:"code"`
			Tid    int64 `json:"tid,omitempty"`
			AppId int64 `json:"appid,omitempty"` */ //内部app id, internal app id
			Name string `json:"name"`
		}

		//url querystring格式定义
		type UrlParam struct {
			/*Code    string `urlenc:"code"`
			Tid    int64 `urlenc:"tid"`
			AppId int64 `urlenc:"appid"`*/
		}

		var req Request
		//var urlParam UrlParam
		//if err := ctxExt.UrlDecode(&urlParam); err != nil {
		//	code = 100
		//	msg = err.Error()
		//	break
		//}
		requestByte := ctxExt.PostBody()
		err := json.Unmarshal(requestByte, &req)
		//req.Tid = utils.BytesToInt64(ctxExt.UrlPeek("tid")) //tenant id
		if err != nil {
			code = 100
			msg = err.Error()
			break
		}
		config, err := vc.appconfigService.GetConfigByWho(*sessionData.SysTokenWho)
		if err != nil {
			code = 100
			msg = err.Error()
			break
		}

		if !config.App_Config_Data.Attr.Is_TenantApp {
			code = 100
			msg = "only support in tenant app"
			break
		}

		//who := common.NewWho(req.Tid, req.AppId, 0)
		newtenant, newmember, err := vc.tenantService.CreateTenantWithMember(sessionData.SysTokenWho, req.Name)
		if err != nil {
			code = 100
			msg = err.Error()
			break
		}

		resp := &Resp{}
		resp.TenantMember = *newmember
		resp.Tenant = *newtenant
		response["data"] = resp // TODO这里返回值要加数据结构
		break
	}

	response["code"] = code
	response["msg"] = msg
	ctxExt.JSON(200, response)
	return
}

func (vc *TenantApiCtrl) TenantUserLogin(ctx *fasthttp.RequestCtx) {
	ctxExt := lego.RequestCtxExtent{ctx}
	response := make(map[string]interface{})
	//data := make(map[string]interface{})

	type Resp struct {
		*userService.LoginUser
		Token string
	}
	code := 0
	msg := "success"

	for {
		//rawcode := string(ctxExt.Peek("code"))
		//tid, _ := utils.StringToInt64(string(ctxExt.Peek("tid"))) //tenant id
		//appid, _ := utils.StringToInt64(string(ctxExt.Peek("appid"))) //tenant id
		//shareid := string(ctx.FormValue("shareid")) // 谁邀请的
		//rawData := string(ctx.PostArgs().Peek("rawData"))
		//BODY内json数据的定义
		type Request struct {
			Code  string `json:"code" vd:"$!=''"`
			Tid   int64  `json:"tid,omitempty" vd:"$>0"`
			AppId int64  `json:"appid,omitempty" vd:"$>0"` //内部app id, internal app id

			EncryptedData string `json:"EncryptedData,omitempty" vd:""`
			iv            string `json:"iv,omitempty" vd:""`
		}

		//url querystring格式定义
		type UrlParam struct {
			Code  string `urlenc:"code"`
			Tid   int64  `urlenc:"tid"`
			AppId int64  `urlenc:"appid"`
		}

		var req Request
		var urlParam UrlParam
		if err := ctxExt.UrlDecode(&urlParam); err != nil {
			code = 100
			msg = err.Error()
			break
		}
		requestByte := ctxExt.PostBody()
		err := json.Unmarshal(requestByte, &req)
		//req.Tid = utils.BytesToInt64(ctxExt.UrlPeek("tid")) //tenant id

		//UrlPara的值优先
		req.Code = urlParam.Code
		if urlParam.Code != "" {
			req.Code = urlParam.Code
		}

		if urlParam.AppId != 0 {
			req.AppId = urlParam.AppId
		}

		if urlParam.Tid != 0 {
			req.Tid = urlParam.Tid
		}

		if err = lego.Validate(req); err != nil {
			code = 100
			msg = err.Error()
			break
		}

		//如果tid==0且app_id==0，返回参数错误
		//fmt.Println(rawData)
		if err != nil {
			code = 100
			msg = err.Error()
			break
		}

		if len(req.Code) <= 0 {
			code = 100
			msg = "参数错误"
			break
		}

		reqwho := common.NewWho(req.Tid, req.AppId, 0)
		hasPermission, err := vc.appManagerService.CheckAppPermission(reqwho)
		if !hasPermission {
			msg = err.Error()
			break
		}
		/*hasPermission, err = vc.appManagerService.CheckAppTenantPermission(*reqwho)
		if !hasPermission{
			msg = err.Error()
			break
		}*/
		User, tokenString, err := vc.wxTenantUserService.UserLogin(*reqwho, req.Code, req.EncryptedData, req.iv)
		if err != nil {
			code = 100
			msg = err.Error()
			break
		}

		resp := &Resp{}
		resp.LoginUser = User
		resp.Token = tokenString

		//data["token"] = tokenString
		response["data"] = resp
		break
	}

	response["code"] = code
	response["msg"] = msg
	ctxExt.JSON(200, response)
	return
}

func (vc *TenantApiCtrl) CheckPermission(ctx *fasthttp.RequestCtx) error {
	ctxExt := lego.RequestCtxExtent{ctx}

	sessionData := common.GetSessionData(&ctxExt)
	appwho := sessionData.AppTokenWho
	isTenantApp := vc.appManagerService.IsTenantApp(*appwho)
	if !isTenantApp {
		return nil //不是租户模式的app不需要检测
	}

	/*tenant := vc.tenantService.GetTenantById(appwho.TenantId)
	if tenant == nil {
		err := fmt.Errorf("not found tid<%d>", appwho.TenantId)
		ctxExt.ResponseWithStateCode200(1, err.Error())
		return err
	}*/

	hasPermission := vc.tenantService.HasPermissionInTenant(appwho, appwho.TenantId, appwho.Uid)
	if !hasPermission {
		err := errors.New("no permission for tenant user")
		ctxExt.ResponseWithStateCode200(1, err.Error())
		return err //无权限，则不可以执行下一个中间件
	}

	return nil

}
